#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <iconv.h>
#include <fcntl.h>
#include <dirent.h>

#include "../includes/utils.h"
#include "../includes/fat-utils.h"


void printBPB( BPB * );
uint8_t loadVolume(Volume * , BPB * );
void printDirEntry( DirEntry * );
void printLongDirEntry( LDirEntry * );
uint32_t getFirstSectorOfCluster(Volume * , uint32_t);
uint32_t getFatEntrySector(Volume * , uint32_t);
uint32_t getFatEntryOffset(Volume * , uint32_t);
int isClusterEnd(uint32_t);
void getFileFromDisk( Volume * , FILE * , uint32_t , uint32_t *);
uint32_t getFirstClusterFromDirEntry(DirEntry *);
void ls(char *);
void full_ls(char *);
//uint32_t pfs_fat_getFreeCluster(BPB * , FSInfo * , int32_t );
FSInfo pfs_fat_readFSInfo(BPB * , int32_t );
uint32_t pfs_fat_fetchChar(LDirEntry *, int8_t );
int8_t pfs_fat_getNameLength(LDirEntry *);
void pfs_fat_extractName( LDirEntry * , uint16_t * , int8_t );
FatFile pfs_fat_openFile(Volume * , char * , uint8_t *);
void printFatFile(FatFile);
void pfs_fat_readdir(Volume * , FatFile * , struct dirent * );
void pfs_fat_toDirent(struct dirent * , DirEntry , LDirEntry, Volume *);
uint8_t pfs_fat_scanRemainingCluster(Volume * , uint32_t , uint32_t);
char *  pfs_get_fileName(LDirEntry *);
void pfs_scanSubDir(Volume * , DirEntry * );
void pfs_fat_unlink(Volume * , char * );

int main(int argc , char * argv[]){

	char buffer[SECTOR_SIZE];
	Volume vol;
	BPB bpb;
	DirEntry rootDirectory;
	LDirEntry longRootDirectory;
	struct dirent de;

	puts("Tamanios de estructuras:");
	printf("\tBPB size is %d.\n" , sizeof(BPB));
	printf("\tFSInfo size is %d.\n" , sizeof(FSInfo));
	printf("\tDirEntry size is %d.\n" , sizeof(DirEntry));
	printf("\tLDirEntry size is %d.\n" , sizeof(LDirEntry));
	printf("\n");

	vol.disk = open("/vfs/fat32.disk.0" , O_RDONLY);
	if ( vol.disk == -1){
		perror("open");
		return EXIT_FAILURE;
	}


	/* Leer la BPB */
	int32_t result = read(vol.disk , &buffer , SECTOR_SIZE);
	if (result != SECTOR_SIZE){
		perror("read");
		return EXIT_FAILURE;
	}

	memcpy(&bpb , buffer , sizeof(BPB));

	loadVolume(&vol , &bpb);
	printf("\n");

	printBPB(&bpb);

	printf("El primer sector de datos es %u ---> byte offset %u\n" , vol.fds , vol.fds * vol.bps);
	printf("\n");


	/* Leer el Long Directory Entry del RootDir */
	off_t offset = lseek(vol.disk , vol.fds * vol.bps , SEEK_SET);
	if ( offset == -1 ){
		perror("lseek");
		return EXIT_FAILURE;
	}

	result = read(vol.disk , &buffer , vol.bps);
	if (result != SECTOR_SIZE){
		perror("read");
		return EXIT_FAILURE;
	}

	memcpy(&longRootDirectory , buffer , sizeof(LDirEntry));
	printLongDirEntry(&longRootDirectory);


	/* Leer el RootDirectory o FirstDataSector */
	memcpy(&rootDirectory , buffer + 32 , sizeof(DirEntry));
	printDirEntry(&rootDirectory);

	uint32_t nextCluster = getFirstClusterFromDirEntry(&rootDirectory);
	printf("El cluster que le sigue  es: %d\n" , nextCluster);

	//Ejemplo con el cluster 3
	printf("El primer sector del cluster 3 es %u ---> byte offset %u\n" ,
	getFirstSectorOfCluster(&vol , 3),
	getFirstSectorOfCluster(&vol , 3) * vol.bps);
		
	FILE * file = fopen("face-01.png" , "w");
	if ( file == NULL ){
		perror("fopen - creando archivo nuevo");
		return EXIT_FAILURE;
	}

	uint32_t left = rootDirectory.DIR_FileSize;

	while (nextCluster != 0){

		getFileFromDisk(&vol , file , nextCluster , &left);

		uint32_t value = 0;
		uint32_t sectorNumberInFat = getFatEntrySector(&vol , nextCluster);
		//printf("sectorNumberInFat: %d\n",sectorNumberInFat);
		uint32_t fatEntryOffset = getFatEntryOffset(&vol , nextCluster);
		//printf("fatEntryOffset: %d\n",fatEntryOffset);
		
		offset = lseek(vol.disk , sectorNumberInFat * vol.bps + fatEntryOffset , SEEK_SET);
		result = read(vol.disk , &value, sizeof(uint32_t));
		if (result != sizeof(uint32_t)){
			perror("read");
			return EXIT_FAILURE;
		}
		
		nextCluster = value;
		nextCluster = (*(uint32_t *) &value) & 0x0FFFFFFF;
		if ( isClusterEnd(value) )
			nextCluster = 0;
		//printf("Cluster: %d\n",nextCluster);
		//printf("\n");
	}
	


	///////////////////////////////// CODIGO DE JOACO //////////////////////////
	char cmd[30], path[50], viejoPath[50];
	strcpy(path, "/");	
	uint8_t control = 1;
	while(1){
		if(control != 1)printf("%s>", viejoPath);
		else printf("%s>", path);
		fgets(cmd, 30, stdin);
		if(!strcmp("ls\n", cmd)) full_ls(buffer);
		if(!strcmp("readdir\n" , cmd)) {
			FatFile fd = pfs_fat_openFile(&vol, NULL, &control);
			//printFatFile(fd);
			while (fd.flag == 1){
				pfs_fat_readdir(&vol , &fd , &de);
				printf("Struct dirent d_name[]: %s\n",de.d_name);
			}
		}
		if(!strcmp("open\n", cmd)){
			strcpy(viejoPath, path);
			strcpy(path, "/tengotrececha/hola/yotmbtengo13c/archivo1.txt");
/*			FatFile fd = pfs_fat_openFile(&vol , path, &control);*/
/*			while (fd.flag == 1){*/
/*				pfs_fat_readdir(&vol , &fd , &de);*/
/*				//printf("Struct dirent d_name[]: %s\n",de.d_name);*/
/*			}*/
		}
		if(!strcmp("unlink\n", cmd)){
			strcpy(path, "/tengotrececha/hola/yotmbtengo13c/archivo1.txt");
			pfs_fat_unlink(&vol, path);
		}

		if(!strcmp("quit\n" , cmd)){
			close(vol.disk);
			fclose(file);
			return EXIT_SUCCESS;
		}
	}
	//////////////////////////////FIN CODIGO DE JOACO //////////////////////////

	return EXIT_SUCCESS;
}

void printBPB( BPB * unaBpb ){
	puts("Detalles del disco:");
        printf("\tBytes per sector: %d\n" , unaBpb->BPB_BytsPerSec );
        printf("\tSectors per cluster: %d\n" , unaBpb->BPB_SecPerClus );
        printf("\tFile Allocation Tables: %d\n" , unaBpb->BPB_NumFATs );
        printf("\tReserved sector count: %d\n" , unaBpb->BPB_ResvdSecCnt );
        printf("\tTotal sectors 32: %d\n" , unaBpb->BPB_TotSec32);
        printf("\tRoot directory entries count: %d\n" , unaBpb->BPB_RootEntCnt );
        printf("\tSectors occupied by one FAT: %d\n" , unaBpb->BPB_FATSz32 );
        printf("\tRoot Cluster Number: %d\n" , unaBpb->BPB_RootClus );
        printf("\n");
}

uint8_t loadVolume(Volume * v , BPB * b ){

	v->bps = b->BPB_BytsPerSec;
	v->spc = b->BPB_SecPerClus;
	v->bpc = v->bps * v->spc;
	v->rsv = b->BPB_ResvdSecCnt;

	v->fatQty = b->BPB_NumFATs;
	v->fatSize = b->BPB_FATSz32;
	v->fatStartSector = v->rsv;

	v->root = b->BPB_RootClus;
	v->sectors = b->BPB_TotSec32;
	v->dataSectors = v->sectors - ( v->rsv + (v->fatQty * v->fatSize) );
	v->clusters = v->dataSectors / v->spc;
	v->fds = v->rsv + (v->fatQty * v->fatSize);

	printf("Clusters totales: %u.\n" , v->clusters);

	if ( v->clusters < 65525 ) {
		printf("El volumen esta formateado en FAT12 o FAT16.\n");
		printf("Esta implementacion soporta unicamente FAT32.\n");
		printf("Saliendo...\n");
		return 0;
	} else {
		printf("Volumen FAT32 valido.\n");
		return 1;
	}
}

void printDirEntry( DirEntry * dir){
	puts("Detalles del directorio:");
	printf("\t 0: %c\n", dir->DIR_Name[0]);
	printf("\t 1: %c\n", dir->DIR_Name[1]);
	printf("\t 2: %c\n", dir->DIR_Name[2]);
	printf("\t 3: %c\n", dir->DIR_Name[3]);
	printf("\t 4: %c\n", dir->DIR_Name[4]);
	printf("\t 5: %c\n", dir->DIR_Name[5]);
	printf("\t 6: %c\n", dir->DIR_Name[6]);
	printf("\t 7: %c\n", dir->DIR_Name[7]);
	printf("\t 8: %c\n", dir->DIR_Name[8]);
	printf("\t 9: %c\n", dir->DIR_Name[9]);
	printf("\t10: %c\n", dir->DIR_Name[10]);

	if ( dir->DIR_Attr == 0x10 ) {
		printf("\tAttribute: es un directorio\n");
	} else printf("\tAttribute: es un archivo\n");

	printf("\tNT Reserved is %d\n",dir->DIR_NTRes);
	printf("\tMiliseconds is %d\n",dir->DIR_CrtTimeTenth);
	printf("\tCreation time is %d\n",dir->DIR_CrtTime);
	printf("\tCreation date is %d\n",dir->DIR_CrtDate);
	printf("\tLast access date is %d\n",dir->DIR_LstAccDate);
	printf("\tFirst Cluser HI is %d\n",dir->DIR_FstClusHI);
	printf("\tLast write time is %d\n",dir->DIR_WrtTime);
	printf("\tLast write date is %d\n",dir->DIR_WrtDate);
	printf("\tFirst Cluster LO is %d\n",dir->DIR_FstClusLO);
	printf("\tFilesize is %d\n",dir->DIR_FileSize);
	printf("\n");
}

void printLongDirEntry( LDirEntry * dir){
	uint16_t utf16name[13];

	puts("Detalles del Long Directory Entry:");
	if ( LDIR_ISLAST(dir->LDIR_Ord) ) //Ver linea 131 del fat-utils.h
		puts("\tUltimo LDirEntry del archivo");

	if ( dir->LDIR_Attr == ATTR_LONG_NAME ){
		printf("\tAttribute: es long name\n");
	} else printf("\tAttribute: no es long name\n");

	printf("\tEl tipo es %d\n" , dir->LDIR_Type);
	printf("\tEl checksum es %d\n" , dir->LDIR_Chksum);

	// Nuevas funcs
	char * utf8name = pfs_get_fileName(dir);
	printf("\tEl nombre es: %s\n" , utf8name);
	printf("\n");
	free(utf8name);
}

uint32_t getFirstSectorOfCluster(Volume * v , uint32_t cluster){
	uint32_t firstSector = ((cluster - 2) * v->spc) + v->fds;
	return firstSector;
}

uint32_t getFatEntrySector(Volume * v , uint32_t cluster){
	uint32_t sectorNumberInFat = v->rsv + (cluster * 4 / v->bps);
	return sectorNumberInFat;
}

uint32_t getFatEntryOffset(Volume * v , uint32_t cluster){
	uint32_t fatEntryOffset = (cluster * 4) % v->bps;
	return fatEntryOffset;
}

int isClusterFree(uint32_t value){
	return (value & 0x0FFFFFFF) == 0x00000000;
}

int isClusterEnd(uint32_t value){
	return (value & 0x0FFFFFFF) >= 0x0FFFFFF8;
}

void getFileFromDisk( Volume * v , FILE * newFile , uint32_t FAT32ClusEntryVal , uint32_t * bytesLeft){
	int8_t index;
	char * buffer = (char *)malloc(SECTOR_SIZE);
	uint64_t sector = getFirstSectorOfCluster(v , FAT32ClusEntryVal);

	for( index = 0 ; index < 8 ; index++ ){

		//printf("Sector es %llu\n", sector + index);
		off_t offset = lseek(v->disk , (sector + index) * v->bps , SEEK_SET);
		if ( offset == -1 ){
			perror("lseek en getFileFromDisk");
			return;
		}

		if ( *bytesLeft >= SECTOR_SIZE){
			int32_t result = read(v->disk , buffer , SECTOR_SIZE);
			if (result != SECTOR_SIZE){
				perror("read en getFileFromDisk");
				return;
			}

			result = fwrite(buffer , 1 , SECTOR_SIZE , newFile);
			if (result != SECTOR_SIZE){
				perror("write en getFileFromDisk");
				return;
			}
			*bytesLeft -= 512;
		} else {
			int32_t result = read(v->disk , buffer , *bytesLeft);
			if (result != *bytesLeft){
				perror("read en getFileFromDisk");
				return;
			}

			result = fwrite(buffer , 1 , *bytesLeft , newFile);
			if (result != *bytesLeft){
				perror("write en getFileFromDisk");
				return;
			}
			break;
		}
		//printf("Bytes left %d.\n",*bytesLeft);
	}

	free(buffer);
}


uint32_t getFirstClusterFromDirEntry(DirEntry * D) {
	uint32_t val = 0;
	
	char *dst = (char *) &val;
	char *src = (char *) &(D->DIR_FstClusLO);
	
	dst[0] = src[0];
	dst[1] = src[1];

	src = (char *) &(D->DIR_FstClusHI);
	dst[2] = src[0];
	dst[3] = src[1];
	
	return val;
}


	///////////////////////////////// CODIGO DE JOACO //////////////////////////
	
void ls(char * buffer){
	DirEntry rootDirectory;
	uint16_t j = 1;
	memcpy(&rootDirectory , buffer + (32 * j), sizeof(DirEntry));
	printf("\tNOMBRE\t\t\t\tATTR\t\t\t\tSIZE\n");
	while(rootDirectory.DIR_Name[0] != 0){
		if(rootDirectory.DIR_Attr == 0x10 || rootDirectory.DIR_Attr == 0x20){
			printf("\t%s\t\t\t%x\t\t\t\t%d\n", rootDirectory.DIR_Name, rootDirectory.DIR_Attr, rootDirectory.DIR_FileSize);
		}
		j++;
		memcpy(&rootDirectory , buffer + (32 * j), sizeof(DirEntry));	
	}
}

	//////////////////////////////FIN CODIGO DE JOACO //////////////////////////

void full_ls(char * buffer){
	DirEntry shortEntry;
	LDirEntry longEntryArray[5];
	uint16_t counter = 0;
	char * bufferOffset = buffer;

	printf("\n\tNOMBRE\t\t\t\tATTR\t\t\t\tSIZE\n");

	memcpy(&longEntryArray[counter] , buffer , sizeof(LDirEntry));
	counter++;

	while( longEntryArray[counter-1].LDIR_Ord != 0xE5 ){
		while ( longEntryArray[counter-1].LDIR_Attr == ATTR_LONG_NAME) {

			if ( LDIR_ISLAST(longEntryArray[0].LDIR_Ord) ){
				// Leer en shortEntry
				bufferOffset += 32;
				memcpy(&shortEntry , bufferOffset , sizeof(DirEntry));
				break;
			} else {
				bufferOffset += 32;
				memcpy(&longEntryArray[counter] , bufferOffset , sizeof(LDirEntry));
				counter++;
			}

		}

		//uint8_t nameLength = pfs_fat_getNameLength(&longEntryArray[counter-1]);
		//uint16_t utf16name[13];
		//pfs_fat_extractName(&longEntryArray[counter-1],utf16name,nameLength);
		//char * utf8name = (char *)calloc(nameLength,sizeof(char));
		//size_t utf8length = 0;
		//unicode_utf16_to_utf8_inbuffer(utf16name , nameLength - 1 , utf8name , &utf8length);
		char * utf8name = pfs_get_fileName(&longEntryArray[counter-1]);

		printf("\t%s\t\t\t%x\t\t\t\t%d\n", utf8name , shortEntry.DIR_Attr, shortEntry.DIR_FileSize);
		free(utf8name);

		//Retoma el ciclo para buscar el siguiente set de entries
		counter = 0;
		bufferOffset += 32;
		memcpy(&longEntryArray[counter] , bufferOffset , sizeof(LDirEntry));
		counter++;
	}
	return;
}

/*
uint32_t pfs_fat_getFreeCluster(BPB * bpb , FSInfo * fs , int32_t disk ){
	uint32_t currentCluster = fs->FSI_Nxt_Free;
	uint32_t freeCluster = fs->FSI_Nxt_Free;
	uint32_t fatEntry;

	uint32_t DataSec = bpb->BPB_TotSec32 - (bpb->BPB_ResvdSecCnt + (bpb->BPB_NumFATs * bpb->BPB_FATSz32));
	uint32_t CountofClusters = DataSec / bpb->BPB_SecPerClus;

	for( ; currentCluster < CountofClusters ; currentCluster++){

		uint32_t sector = getFatEntrySector(bpb , currentCluster);
		uint32_t offset = getFatEntryOffset(bpb , currentCluster);

		lseek(disk , sector * 512 + offset , SEEK_SET);
		int16_t result = read(disk , &fatEntry, sizeof(uint32_t));
		if (result != sizeof(uint32_t))
			perror("read");

		if( isClusterFree(fatEntry) ){
			fs->FSI_Nxt_Free = currentCluster;
			break;
		}
	}
	return freeCluster;
}
*/

FSInfo pfs_fat_readFSInfo(BPB * unaBpb , int32_t disk){
	FSInfo fsinfo;
	lseek(disk , unaBpb->BPB_FSInfo * 512  , SEEK_SET);
	int16_t result = read(disk , &fsinfo, sizeof(FSInfo));
	if (result != sizeof(FSInfo))
		perror("read");

	return fsinfo;
}

uint32_t pfs_fat_fetchChar(LDirEntry *D, int8_t n) {
    int i = (n % 13);

    if ( i <= 4  ) return D->LDIR_Name1[i];
    if ( i <= 10 ) return D->LDIR_Name2[i-5];
    return D->LDIR_Name3[i-11];
}

int8_t pfs_fat_getNameLength(LDirEntry * ldirentry){
	uint8_t i;
	uint16_t character;

    for ( i=0 ; i<13 ; i++) {
    	character = pfs_fat_fetchChar(ldirentry , i);
		if ( LFN_ISNULL(character) )
			return (i + 1);
    }

    return (i + 1);
}

void pfs_fat_extractName( LDirEntry * d, uint16_t * dest, int8_t length) {
	int8_t i;

	for (i=0; i < (length - 1); i++) {
    	dest[i] = pfs_fat_fetchChar(d , i);
    }

    dest[length - 1] = 0x00;

    return;
}

uint8_t pfs_fat_parser(uint16_t * pos, char ** path, char ** directorio){
	//El path debe ser un fullpath
	
	if((*path)[(*pos)] != '/'){
		if(strlen((*path)) == 0) {
			return 1;
		}
		else{
			puts("Directorio incorrecto");
			return 2;
		}
	}
	else{
		if((*path)[(*pos)] == '/' && (strlen((*path)) - (*pos)) - 1 > 1){
			uint16_t i = 0;
			(*pos)++;
			(*directorio)=(char *)malloc(13);
			bzero((*directorio), sizeof((*directorio)));
			while((*path)[(*pos)] != '/' && (*pos) <= strlen((*path))){
				(*directorio)[i]= (*path)[(*pos)];
				i++;
				(*pos)++;
			}
/*			char newPath[strlen((*path)) - strlen((*directorio))];*/
/*			uint16_t k = (*pos);*/
/*			i = 0;*/
/*			while( k <= strlen((*path))){*/
/*				newPath[i] = (*path)[k];*/
/*				k++;*/
/*				i++;*/
/*			}*/
			if( (*directorio)[strlen((*directorio)) - 1] >= 127 ) (*directorio)[strlen((*directorio)) - 1] = '\0';
			return 0;
		}
		else return 1;
	}
}

FatFile pfs_fat_openFile(Volume * v , char * path, uint8_t * control){
	FatFile fd;
	uint32_t next;

	if ( path == NULL || !strcmp(path,"/") ){
		fd.source = v->root;
		fd.sourceOffset = 0;
		uint32_t sector = getFatEntrySector(v,v->root);
		uint32_t offset = getFatEntryOffset(v,v->root);
		lseek(v->disk , sector * 512 + offset ,  SEEK_SET);
		read(v->disk , &next , sizeof(uint32_t));
		if( FAT32_ISEOC(next) )
			fd.nextCluster = 0;
		else
			fd.nextCluster = next;
		fd.dirEntryOffset = 0;
		fd.flag = 1;
		fd.dirType = 0;
		return fd;
	} // falta desarrollar else para cuando no es el root directory
	else{
		char * directorio;
		char * utf8name;
		char buffer[v->bps];
		LDirEntry longEntry;
		DirEntry sDirEntry;
		
		uint32_t offset = v->fds * v->bps, sector, currentCluster;
		uint16_t pos = 0;
		uint8_t flag = 0;

		if(path[strlen(path) - 1] != '/'){
			path[strlen(path)] = '/';
		}

		flag = pfs_fat_parser(&pos, &path, &directorio);		
		
		if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
		if(read(v->disk , &longEntry , 32) != 32) {perror("read");	exit(1);}
		utf8name = pfs_get_fileName(&longEntry);
		
		while(flag == 0){ //flag: 0 si el directorio sigue, 1 si termino, 2 si hay error de sintaxis
			//printf("--------------Pos: %d\tFLAG: %d\tPath: %s\tDirectorio: %s--------------\n", pos, flag, path, directorio);
			while(longEntry.LDIR_Ord != 0x00 && strcmp(utf8name, directorio)){
				//Buscamos en el cluster hasta que encontremos el archivo o directorio o hasta el fin del cluster
				offset += 32;
				if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
				if(read(v->disk , &longEntry , 32) != 32) {perror("read");	exit(1);}
				if(longEntry.LDIR_Attr == ATTR_LONG_NAME){
					utf8name = pfs_get_fileName(&longEntry);
					//printf("utf8name: %s\n", utf8name);
				}
			}
			
			if(longEntry.LDIR_Ord == 0x00){
				printf("\"%s\" no existe\n", directorio);
				return;
			}
			if(!strcmp(utf8name, directorio)){
				printf("\"%s\" encontrado\n", utf8name);
				while(!LDIR_ISLAST(longEntry.LDIR_Ord)){
					//Recorremos la cadena de LDirEntrys para buscar el shortDirEntry
					offset += 32;
					if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
					if(read(v->disk , &longEntry , 32) != 32) {perror("read");	exit(1);}
				}
				if(LDIR_ISLAST(longEntry.LDIR_Ord)){
					//Acomodamos el offset para leer el shortDirEntry
					offset += 32;
				}
			}
			
			if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
			if(read(v->disk , &sDirEntry , 32) != 32) {perror("read");	exit(1);}
			currentCluster = next;
			next = getFirstClusterFromDirEntry(&sDirEntry);
			sector = getFirstSectorOfCluster(v , next);
			
			flag = pfs_fat_parser(&pos, &path, &directorio);			
			if(flag != 0){
				(*control) = flag;			
				break;
			}
			offset = sector * v->bps + 32;			
			
		}
		//Llenado de structura fd	
		free(utf8name);
		free(directorio);

		fd.source = currentCluster;
		fd.sourceOffset = 0;
		fd.nextCluster = getFirstClusterFromDirEntry(&sDirEntry);
		fd.dirEntryOffset = offset -= 32;
		fd.flag = 1;
		fd.dirType = 1;
		
		return fd;
	}
}

void pfs_fat_unlink(Volume * v , char * path){
	uint8_t control;
	DirEntry sDirEntry;
	FatFile fd = pfs_fat_openFile(v, path, &control);
	uint32_t sector = getFirstSectorOfCluster(v , fd.source);
	uint32_t nextCluster, EntryValue;
	
	//Borrado de DirEntry
	if(lseek(v->disk, fd.dirEntryOffset + 32, SEEK_SET) == -1) {perror("lseek en unlink"); exit(1);};
	if(read(v->disk, &sDirEntry , 32) != 32) {perror("read en unlink");	exit(1);};
	lseek(v->disk, fd.dirEntryOffset + 32, SEEK_SET);
	if(pfs_fat_scanRemainingCluster(v, sector , fd.dirEntryOffset)){
		write(v->disk, "0x00", sizeof(DirEntry));
	} 
	else{
		write(v->disk, "0xE5", sizeof(DirEntry));
	}

	//Borrado de la chain en la FAT
	uint32_t sectorNumberInFat = getFatEntrySector(v , nextCluster);
	uint32_t fatEntryOffset = getFatEntryOffset(v , nextCluster);
	if(lseek(v->disk , sectorNumberInFat * v->bps + fatEntryOffset , SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);};
	if(read(v->disk, &EntryValue, sizeof(uint32_t)) != sizeof(uint32_t)) {perror("read en unlink");	exit(1);};
	if(lseek(v->disk , sectorNumberInFat * v->bps + fatEntryOffset , SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);};
	printf("%x\n", EntryValue);
	write(v->disk, "0x00000000", sizeof(uint32_t));
	if(lseek(v->disk , sectorNumberInFat * v->bps + fatEntryOffset , SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);};
	if(read(v->disk, &EntryValue, sizeof(uint32_t)) != sizeof(uint32_t)) {perror("read en unlink");	exit(1);};
	printf("%x\n", EntryValue);	
	while(!FAT32_ISEOC(EntryValue)){
		sectorNumberInFat = getFatEntrySector(v , nextCluster);
		fatEntryOffset = getFatEntryOffset(v , nextCluster);
		if(lseek(v->disk , sectorNumberInFat * v->bps + fatEntryOffset , SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);};
		if(read(v->disk, &EntryValue, sizeof(uint32_t)) != sizeof(uint32_t)) {perror("read en unlink");	exit(1);};
		if(lseek(v->disk , sectorNumberInFat * v->bps + fatEntryOffset , SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);};
		write(v->disk, "0x00000000", sizeof(uint32_t));		
	}
	
}






/*void pfs_fat_unlink(Volume * v , char * path){*/
/*	uint32_t sectorNumberInFat, fatEntryOffset, nextCluster, value, sector, offset;*/
/*	uint8_t control;*/
/*	FatFile fd = pfs_fat_openFile(v, path, &control);*/
/*	DirEntry sDirEntry, aux_sDirEntry;*/
/*	nextCluster = fd.nextCluster;*/
/*	*/
/*	do{*/
/*		sector = getFirstSectorOfCluster(v , nextCluster);*/
/*		offset = sector * v->bps + 32;*/
/*		if(control && fd.dirType) { //Para skipear "." y ".." si es un subdirectorio y el primer lDirEntry*/
/*			offset += 96;*/
/*			control = 0;*/
/*		}*/
/*		if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);}*/
/*		if(read(v->disk , &sDirEntry , 32) != 32) {perror("read en unlink");	exit(1);}*/
/*		if(lseek(v->disk ,  32, SEEK_CUR) == -1 ) {perror("lseek en unlink"); exit(1);}*/
/*		if(read(v->disk , &aux_sDirEntry , 32) != 32) {perror("read en unlink");	exit(1);}*/
/*		if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);}*/
/*		if(aux_sDirEntry.DIR_Name == 0x00 || offset + 32 == 4096){*/
/*			write(v->disk, "0x00", 11);		*/
/*		}*/
/*		else{*/
/*			write(v->disk, "0xE5", 11);*/
/*		}*/
/*		*/
/*		*/
/*		sectorNumberInFat = getFatEntrySector(v , nextCluster);*/
/*		fatEntryOffset = getFatEntryOffset(v , nextCluster);*/
/*		if(lseek(v->disk , sectorNumberInFat * v->bps + fatEntryOffset, SEEK_SET) == -1 ) {perror("lseek en unlink"); exit(1);}*/
/*		puts("FORRO");*/
/*		if(read(v->disk , &value , sizeof(uint32_t)) != 32) {perror("read en unlink"); exit(1);}*/
/*		puts("FORRO2");*/
/*		if(write(v->disk, "0x00000000", sizeof(uint32_t)) != sizeof(uint32_t)) {perror("write en unlink"); exit(1);}	*/
/*		nextCluster = value;*/
/*		nextCluster = (*(uint32_t *) &value) & 0x0FFFFFFF;		*/
/*	}while(!FAT32_ISEOC(value));*/
/*}*/

void pfs_fat_readdir(Volume * v , FatFile * f, struct dirent * de){
	uint32_t offset = f->dirEntryOffset;
	uint32_t sector = getFirstSectorOfCluster(v,v->root);
	uint8_t result;
	LDirEntry ldirentry;
	DirEntry direntry;

	if(f->dirType){
		sector = getFirstSectorOfCluster(v , f->nextCluster);
		offset = sector * 512 + 64;
		if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
		if(read(v->disk , &ldirentry , 32) != 32) {perror("read");	exit(1);}

		while(ldirentry.LDIR_Ord != 0x00){
			offset += 32;
			if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
			if(read(v->disk , &direntry , 32) != 32) {perror("read");	exit(1);}

			if( pfs_fat_scanRemainingCluster(v,sector,offset) )
			f->flag = 0;

			pfs_fat_toDirent(de,direntry,ldirentry,v);
			printf("Struct dirent d_name[]: %s\n",de->d_name);

			offset += 32;
			if(lseek(v->disk ,  offset, SEEK_SET) == -1 ) {perror("lseek"); exit(1);}
			if(read(v->disk , &ldirentry , 32) != 32) {perror("read");	exit(1);}
		}
	}
	else{
		if( offset >= v->bpc ){
			sector = getFirstSectorOfCluster(v,f->nextCluster);
			offset = 0;
			//f->nextCluster = algunCluster; --->> Hacer logica para buscar el siguiente cluster y almacenarlo
		}

		ldirentry.LDIR_Ord = 0x00; // Fuerzo la entrada al ciclo
		while ( DIRENT_ISFREE(ldirentry.LDIR_Ord) ) {
			lseek(v->disk , sector * v->bps + offset , SEEK_SET);
			if ( (result = read(v->disk , &ldirentry , 32)) != 32 ){ //Esta linea lee el LDirEntry del archivo
				perror("readdir - error en read ldirentry");
				return;
			}
			offset += 32;

			if( offset == v->bpc && FAT32_ISEOC(f->nextCluster) ){
				f->flag = 0;
				return;
			}//analizar condicion de "else" por si efectivamente hay next cluster
		}

		if( LDIR_ISLAST(ldirentry.LDIR_Ord) ){
			lseek(v->disk , sector * v->bps + offset , SEEK_SET);
			if ( (result = read(v->disk , &direntry , 32)) != 32 ){ //Esta linea lee el DirEntry del archivo
				perror("readdir - error en read direntry");
				return;
			}
			offset += 32;
		} else {
			f->flag = 0;
			return;
		}

		if( pfs_fat_scanRemainingCluster(v,sector,offset) )
			f->flag = 0; // ---> Se llego al final de cluster y no hay mas DirEntries para levantar
						// Habria que ver que hacer si siguen mas DirEntries en otro cluster ademas del actual


		f->dirEntryOffset = offset;

		pfs_fat_toDirent(de,direntry,ldirentry,v);
		printf("Struct dirent d_name[]: %s\n",de->d_name);
	}
}

void pfs_fat_toDirent(struct dirent * de , DirEntry direntry , LDirEntry ldirentry , Volume * v){
	uint8_t length = pfs_fat_getNameLength(&ldirentry);

	uint16_t utf16name[13];
	pfs_fat_extractName(&ldirentry,utf16name,length);

	char * utf8name = (char *)calloc(length,sizeof(char));

	size_t utf8length = 0;
	unicode_utf16_to_utf8_inbuffer(utf16name , length - 1 , utf8name , &utf8length);

	strcpy(de->d_name,utf8name);
	de->d_ino = getFirstClusterFromDirEntry(&direntry);
	free(utf8name);

	if ( direntry.DIR_Attr == ATTR_DIRECTORY ){
		de->d_type = DT_DIR;
		//pfs_scanSubDir(v,&direntry);
	}
	else
		de->d_type = DT_REG;
}

uint8_t pfs_fat_scanRemainingCluster(Volume * v, uint32_t s , uint32_t o){

	LDirEntry l;

	l.LDIR_Ord = 0x00;
	while( DIRENT_ISFREE(l.LDIR_Ord) && (o < v->bpc) ){
		lseek(v->disk , s * v->bps + o , SEEK_SET);
		read(v->disk , &l , sizeof(LDirEntry));
		o += 32;
	}

	if ( o >= v->bpc )
		return 1;

	return 0;
}

char *  pfs_get_fileName(LDirEntry * l){
	uint8_t nameLength = pfs_fat_getNameLength(l);

	uint16_t utf16name[13];
	pfs_fat_extractName(l , utf16name , nameLength);

	char * utf8name = (char *)calloc(nameLength,sizeof(char));
	size_t utf8length = 0;

	unicode_utf16_to_utf8_inbuffer(utf16name , nameLength - 1 , utf8name , &utf8length);

	return utf8name;
}

void pfs_scanSubDir(Volume * v , DirEntry * direntry){
	char content[v->bps];
	DirEntry entry;
	LDirEntry lentry;
	uint8_t i;

	uint32_t firstCluster = getFirstClusterFromDirEntry(direntry);
	uint32_t sector = getFirstSectorOfCluster(v , firstCluster);

	lseek(v->disk , sector * v->bps , SEEK_SET );
	read(v->disk , content , v->bps);

	for( i = 0 ; i < 5 ; i++){

		memcpy(&entry , content + (i * 32) , sizeof(DirEntry));
		memcpy(&lentry , content + (i * 32), sizeof(LDirEntry));

		if( lentry.LDIR_Attr != ATTR_LONG_NAME ){
			printDirEntry(&entry);
		} else {
			printLongDirEntry(&lentry);
		}

	}
}


